﻿using Casamiel.Common;
using Casamiel.Domain.Entity;
using Casamiel.Domain;
using Enyim.Caching;
using Microsoft.Extensions.Options;
using Smooth.IoC.UnitOfWork.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Casamiel.Application.Services
{
	public sealed class WxService:IWxService
    {
		private readonly IWxOpenIdRepository wxOpen;
		private readonly IMiniAppSettingsRepository miniApp;
        private readonly IMemcachedClient _memcachedClient;
        private readonly string _memcachedPre = "";
        private readonly bool _cacheEnable = false;
        private readonly int _cacheSeconds = 720;
    
        /// <summary>
        /// 
        /// </summary>
        /// <param name="wxOpenIdRepository">Wx open identifier repository.</param>
        /// <param name="miniAppSettings">Mini app settings.</param>
        /// <param name="memcachedClient">Memcached client.</param>
        /// <param name="snapshot">Snapshot.</param>
        public WxService(IWxOpenIdRepository wxOpenIdRepository,IMiniAppSettingsRepository miniAppSettings,IMemcachedClient memcachedClient, IOptionsSnapshot<CasamielSettings> snapshot)
		{
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }
            wxOpen = wxOpenIdRepository;
			miniApp = miniAppSettings;
            _memcachedClient = memcachedClient;
            _cacheEnable = snapshot.Value.CacheEnable;
            _memcachedPre = snapshot.Value.MemcachedPre;
		}

        public async Task<List<Domain.Entity.MiniAppSettings>> GetMiniAppSettingsList<TSession>() where TSession : class, ISession
        {
            var list = await miniApp.GetAllAsync<TSession>().ConfigureAwait(false);
            return list.ToList();
        }
       
         /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TSession"></typeparam>
        /// <param name="appId"></param>
        /// <returns></returns>
        public async	Task<Domain.Entity.MiniAppSettings> FindAsync<TSession>(string appId) where TSession : class, ISession
        {
            var _cacheKey = _memcachedPre+  Constant.MINIAPPPREFIX+appId;
            Domain.Entity.MiniAppSettings entity;
            if(_cacheEnable){
                var result = await _memcachedClient.GetAsync<Domain.Entity.MiniAppSettings>(_cacheKey).ConfigureAwait(false);
                if (result.Success)
                {
                    entity = result.Value;
                }
                else
                {
                    entity = await miniApp.FindAsync<TSession>(appId).ConfigureAwait(false);
                    await _memcachedClient.AddAsync(_cacheKey, entity, _cacheSeconds).ConfigureAwait(false);
               }
            }
            entity = await miniApp.FindAsync<TSession>(appId).ConfigureAwait(false);
            return entity;
		}
		public async Task<WxOpenId> GetAsync<TSession>(string openid, string appId) where TSession : class, ISession
		{
			return await wxOpen.GetByOpenidAppidAsync<TSession>(openid, appId).ConfigureAwait(false);
		}
		public async Task AddAsync<TSession>(WxOpenId entity) where TSession : class, ISession
		{
			 await 	wxOpen.SaveAsync<TSession>(entity).ConfigureAwait(false);
		}
		public async Task<bool> UpdateAsync<TSession>(WxOpenId entity) where TSession : class, ISession
		{
			return	await wxOpen.UpdateAsync<TSession>(entity).ConfigureAwait(false);
		}
		public async Task<WxOpenId> GetByIdAsync<TSession>(int id) where TSession : class, ISession
		{
			return await wxOpen.GetByIdAsync<TSession>(id).ConfigureAwait(false);
		}
        /// <summary>
        /// Gets the by union identifier async.
        /// </summary>
        /// <returns>The by union identifier async.</returns>
        /// <param name="unionId">Union identifier.</param>
        /// <typeparam name="TSession">The 1st type parameter.</typeparam>
        public async Task<WxOpenId> GetByUnionIdAsync<TSession>(string unionId)where TSession : class, ISession
        {
            return await wxOpen.GetByUnionIdAsync<TSession>(unionId).ConfigureAwait(false);
        }
        /// <summary>
        /// Updates the by moible async.
        /// </summary>
        /// <returns>The by moible async.</returns>
        /// <param name="mobile">Mobile.</param>
        /// <typeparam name="TSession">The 1st type parameter.</typeparam>
        public async   Task UpdateByMoibleAsync<TSession>(string mobile) where TSession : class, ISession{
            await wxOpen.UpdateByMoibleAsync<TSession>(mobile).ConfigureAwait(false);
        }

        /// <summary>
        /// Gets the by moible async.
        /// </summary>
        /// <returns>The by moible async.</returns>
        /// <param name="mobile">Mobile.</param>
        /// <typeparam name="TSession">The 1st type parameter.</typeparam>
        public async Task<WxOpenId> GetByMoibleAsync<TSession>(string mobile) where TSession : class, ISession
        {
              return   await wxOpen.GetByMoibleAsync<TSession>(mobile).ConfigureAwait(false);
        }
        /// <summary>
        /// Gets the by union identifier app identifier async.
        /// </summary>
        /// <returns>The by union identifier app identifier async.</returns>
        /// <param name="unionId">Union identifier.</param>
        /// <param name="appId">App identifier.</param>
        /// <typeparam name="TSession">The 1st type parameter.</typeparam>
        public async Task<WxOpenId> GetByUnionIdAppIdAsync<TSession>(string unionId, string appId) where TSession : class, ISession
        {
            return await wxOpen.GetByUnionIdAppIdAsync<TSession>(unionId, appId).ConfigureAwait(false);
        }

        /// <summary>
        /// Gets the by app identifier mobile async.
        /// </summary>
        /// <returns>The by app identifier mobile async.</returns>
        /// <param name="appId">App identifier.</param>
        /// <param name="mobile">Mobile.</param>
        /// <typeparam name="TSession">The 1st type parameter.</typeparam>
        public async Task<WxOpenId> GetByAppIdMobileAsync<TSession>(string appId,string mobile) where TSession : class, ISession
        {
            return await wxOpen.GetByAppIdMobileAsync<TSession>( appId, mobile).ConfigureAwait(false);
        }
    }
}
